package com.huawang.mdesign.model.service.inter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrBuilder;
import com.google.common.collect.Lists;
import com.huawang.business.constants.ErrorCode;
import com.huawang.business.dto.ModelPropertyInfo;
import com.huawang.business.dto.project.Project;
import com.huawang.business.entity.matrix.CustomListHolder;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.service.judge.BusinessJudgeService;
import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.business.service.model.core.ModelPropertyInfoService;
import com.huawang.business.service.model.core.project.ProjectManager;
import com.huawang.business.service.navigation.INavigationService;
import com.huawang.business.util.InstanceVoUtils;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.semantics.entity.MapOperation;
import com.huawang.core.semantics.service.query.IHierarchyService;
import com.huawang.core.semantics.service.query.IJudgeService;
import com.huawang.core.semantics.service.query.IRelationService;
import com.huawang.mdesign.model.service.constant.ElementCheckRuleKey;
import com.huawang.mdesign.model.service.constant.ValidationSeverityEnum;
import com.huawang.mdesign.model.service.dto.ValidElementDTO;
import com.huawang.mdesign.model.service.dto.ValidSpecifiedRangeElementDTO;
import com.huawang.mdesign.model.service.dto.ValidationModelQueryDTO;
import com.huawang.mdesign.model.service.util.LogUtil;
import com.huawang.mdesign.model.service.vo.ValidationModelInstanceVo;
import com.huawang.mdesign.model.service.vo.ValidatorAnnoation;
import com.huawang.mdesign.model.service.vo.ValidatorResultVo;
import com.huawang.mdesign.model.service.facade.validate.IValidator;
import com.huawang.mdesign.model.service.facade.validate.config.ElementCheckRuleManager;
import com.huawang.mdesign.model.service.facade.validate.config.ValidatorManage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Primary
@Slf4j
public class ValidationService {

    @Autowired
    private ValidatorManage validatorManage;

    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private IHierarchyService hierarchyService;

    @Autowired
    private BusinessJudgeService businessJudgeService;

    @Autowired
    private ElementCheckRuleManager elementCheckRuleManager;

    @Autowired
    private ProjectShareService projectShareService;

    @Autowired
    private IJudgeService iJudgeService;

    @Autowired
    private ProjectManager projectManager;

    @Autowired
    private INavigationService navigationService;

    @Autowired
    private IRelationService relationService;

    private static final int PARTITION_SIZE = 50;


    private static final Set<String> VALIDATION_GROUP_STEREOTYPES = Stream.of(UMLDefinitionConstants.Customization_ValidationSuite,
            UMLDefinitionConstants.Customization_ActivityValidationSuite, UMLDefinitionConstants.Customization_SystemValidationSuite).collect(Collectors.toSet());


    private static final Set<String> VALIDATION_STEREOTYPES = Stream.concat(
            VALIDATION_GROUP_STEREOTYPES.stream(),
            Stream.of(UMLDefinitionConstants.Customization_ValidationRule)).collect(Collectors.toSet());

    private static final Set<String> STEREOTYPES = Stream.concat(
            VALIDATION_STEREOTYPES.stream(),
            Stream.of(UMLDefinitionConstants.Package,
                    UMLDefinitionConstants.Model,
                    UMLDefinitionConstants.Profile)).collect(Collectors.toSet());
    /**
     * 校验分组、校验规则查询属性
     */
    private static final List<String> VALIDATION_QUERY_PROPERTIES = Stream.of(UMLDefinitionConstants.NamedElement_name,
            UMLDefinitionConstants.NamedElement_qualifiedName, UMLDefinitionConstants.Element_appliedStereotype).collect(Collectors.toList());
    /**
     * 校验规则查询属性
     */
    private static final List<String> VALIDATION_RULE_QUERY_PROPERTIES = Stream.of(
            UMLDefinitionConstants.Customization_ValidationRule_Abbreviation,
            UMLDefinitionConstants.Customization_ValidationRule_ValidationObjectType,
            UMLDefinitionConstants.Customization_ValidationRule_ValidationRule,
            UMLDefinitionConstants.Customization_ValidationRule_RuleType,
            UMLDefinitionConstants.Customization_ValidationRule_Severity,
            UMLDefinitionConstants.Customization_ValidationRule_ErrorMessage).collect(Collectors.toList());


    private static final List<String> PROPERTY_IDS = Stream.of(
            UMLDefinitionConstants.Property_class,
            UMLDefinitionConstants.BehavioralFeature_method,
            UMLDefinitionConstants.Operation_ownedParameter,
            UMLDefinitionConstants.InformationFlow_realizingActivityEdge,
            UMLDefinitionConstants.InformationFlow_realizingConnector,
            UMLDefinitionConstants.InformationFlow_realizingMessage,
            UMLDefinitionConstants.InstanceSpecification_classifier,
            UMLDefinitionConstants.Element_appliedStereotype,
            UMLDefinitionConstants.StructuredClassifier_ownedConnector,
            UMLDefinitionConstants.Association_memberEnd,
            UMLDefinitionConstants.Dependency_client,
            UMLDefinitionConstants.Dependency_supplier,
            UMLDefinitionConstants.TypedElement_type,
            UMLDefinitionConstants.Connector_end,
            UMLDefinitionConstants.EncapsulatedClassifier_ownedPort,
            UMLDefinitionConstants.Port_isConjugated,
            UMLDefinitionConstants.Class_ownedOperation,
            UMLDefinitionConstants.Property_aggregation,
            UMLDefinitionConstants.A_general_generalization_generalization,
            UMLDefinitionConstants.Behavior_ownedParameter,
            UMLDefinitionConstants.BehavioredClassifier_ownedBehavior,
            UMLDefinitionConstants.Slot_definingFeature,
            UMLDefinitionConstants.Slot_value,
            UMLDefinitionConstants.Element_constraints,
            UMLDefinitionConstants.Region_subvertex,
            UMLDefinitionConstants.SysML_AbstractRequirement_tracedTo,
            UMLDefinitionConstants.Stereotype_metaClass,
            UMLDefinitionConstants.Activity_node).collect(Collectors.toList());

    @NotNull
    public List<ValidatorResultVo> checkProject(final String projectId) {
        LogUtil.printOnlineLogs("checkProject -> projectId: ", projectId);
        List<MetaClassInstance> elements = internalUmlService.querySpecifiedInstanceList(projectId,
                UMLDefinitionConstants.Element, false);
        List<List<MetaClassInstance>> s = ListUtils.partition(elements, 1000);
        List<ValidatorResultVo> checkResult = new ArrayList<>();
        CompletableFuture<Void> allOf = CompletableFuture.allOf(s.stream().map(t ->
                CompletableFuture.supplyAsync(() ->
                                createValidatorResultVo(projectId,
                                        modelPropertyInfoService.createModelPropertyInfoList(projectId, t,
                                                PROPERTY_IDS)))
                        .thenApplyAsync(checkResult::addAll)).toArray(CompletableFuture[]::new));

        allOf.join();
        return checkResult;
    }

    public List<ValidatorResultVo> checkElementsByRules(ValidSpecifiedRangeElementDTO validElementDto) {
        LogUtil.printSerializeOnlineLogs("checkElementsByRules: ", validElementDto);
        String projectId = validElementDto.getProjectId();
        //获取到所有的校验规则
        List<String> ruleInstanceIds = validElementDto.getRuleInstanceIds();
        List<MetaClassInstance> ruleMetaClassInstances = internalUmlService.fetchInstanceByIds(ruleInstanceIds, projectId);
        Map<String, ModelPropertyInfo> validationRuleModelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, ruleMetaClassInstances, VALIDATION_RULE_QUERY_PROPERTIES);

        //内置校验规则的标志符
        Map<String, ModelPropertyInfo> builtInValidationAbbreviationModelPropertyInfoMap = new HashMap<>();
        //自定义校验规则，需要走脚本表达式逻辑进行校验
        Map<String, ModelPropertyInfo> customizationValidationRuleModelPropertyInfoMap = new HashMap<>();
        for (MetaClassInstance ruleMetaClassInstance : ruleMetaClassInstances) {
            String validationRuleInstanceId = ruleMetaClassInstance.getId();
            ModelPropertyInfo modelPropertyInfo = validationRuleModelPropertyInfoMap.get(validationRuleInstanceId);
            MetaClassInstance ruleTypeInstance = modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_RuleType);
            if (Objects.equals(ruleTypeInstance.getId(), UMLDefinitionConstants.Customization_RuleType_Customization)) {
                String validationRule = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Customization_ValidationRule_ValidationRule);
                if (StringUtils.isNotBlank(validationRule)) {
                    customizationValidationRuleModelPropertyInfoMap.putIfAbsent(validationRuleInstanceId, modelPropertyInfo);
                }
                continue;
            }
            String validationRuleAbbreviation = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Customization_ValidationRule_Abbreviation);
            if (StringUtils.isNotBlank(validationRuleAbbreviation)) {
                builtInValidationAbbreviationModelPropertyInfoMap.putIfAbsent(validationRuleAbbreviation, modelPropertyInfo);
            }
        }
        //获取指定范围下面所有的元素,根据是否需要查询模型子元素配置，选择不同的获取模型方式
        List<MetaClassInstance> elements;
        if (Objects.equals(validElementDto.getIsCheckChildren(), Boolean.TRUE)) {
            elements = hierarchyService.getChildrenCascade(projectId, validElementDto.getInstanceIds(), true);
        } else {
            elements = internalUmlService.fetchInstanceByIds(validElementDto.getInstanceIds(), projectId);
        }
        //根据是否需要去除只读元素配置，对模型进行过滤
        if (Objects.equals(validElementDto.getExcludeReadOnly(), Boolean.TRUE)) {
            Map<String, Boolean> readOnlyMap = businessJudgeService.isReadOnly(projectId, elements);
            elements = elements.stream().filter(e -> readOnlyMap.containsKey(e.getId()) && Objects.equals(readOnlyMap.get(e.getId()), Boolean.FALSE)).collect(Collectors.toList());
        }


        //如果勾选的内置的校验规则不为空
        List<ValidatorResultVo> checkResult = new ArrayList<>();

        //如果勾选了内置校验规则的话，进行内置规则校验
        if (MapUtils.isNotEmpty(builtInValidationAbbreviationModelPropertyInfoMap)) {
            List<ValidatorResultVo> checkByBuiltinValidationRules = checkByBuiltinValidationRules(validElementDto, builtInValidationAbbreviationModelPropertyInfoMap, elements);
            checkResult.addAll(checkByBuiltinValidationRules);
        }

        //如果勾选了自定义校验规则的话，进行自定义规则校验，走脚本表达式校验逻辑
        if (MapUtils.isNotEmpty(customizationValidationRuleModelPropertyInfoMap)) {
            List<ValidatorResultVo> checkByCustomizationValidationRules = checkByCustomizationValidationRules(validElementDto, customizationValidationRuleModelPropertyInfoMap, elements);
            checkResult.addAll(checkByCustomizationValidationRules);
        }


        return checkResult;

    }

    /**
     * 使用自定义校验规则校验模型
     *
     * @param validElementDto
     * @param customizationValidationRuleModelPropertyInfoMap
     * @param elements
     * @return
     */
    private List<ValidatorResultVo> checkByCustomizationValidationRules(ValidSpecifiedRangeElementDTO validElementDto,
                                                                        Map<String, ModelPropertyInfo> customizationValidationRuleModelPropertyInfoMap,
                                                                        List<MetaClassInstance> elements) {
        String projectId = validElementDto.getProjectId();
        Map<String, List<MapOperation>> validationRuleExpressionMap = new HashMap<>();
        Map<String, Set<String>> validationRuleTypesMap = new HashMap<>();
        customizationValidationRuleModelPropertyInfoMap.forEach((instanceId, modelPropertyInfo) -> {
            String validationRule = modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Customization_ValidationRule_ValidationRule);
            List<MapOperation> mapOperationList = InstanceVoUtils.transferCustomizeColumnInfoJsonToMapOperationList(validationRule);
            if (CollectionUtils.isNotEmpty(mapOperationList)) {
                validationRuleExpressionMap.putIfAbsent(instanceId, mapOperationList);
            }

            List<MetaClassInstance> validationObjectTypeInstances = modelPropertyInfo.queryListInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_ValidationObjectType);
            Set<String> typesSet = validationObjectTypeInstances.stream().map(MetaClassInstance::getId).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(typesSet)) {
                validationRuleTypesMap.putIfAbsent(instanceId, typesSet);
            }

        });
        Map<String, Set<String>> elementIdGivenTypesMap = internalUmlService.getGivenTypes(projectId, elements);

        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, elements, Collections.singletonList(UMLDefinitionConstants.NamedElement_qualifiedName));
        Map<MetaClassInstance, Set<String>> elementInstanceGivenTypesMap = elementIdGivenTypesMap.entrySet().stream().
                collect(Collectors.toMap(entry -> modelPropertyInfoMap.get(entry.getKey()).getInstance(), Map.Entry::getValue, (k1, k2) -> k1));

        //过滤出每种自定义逻辑作用的模型
        Map<String, List<MetaClassInstance>> validationRuleEffectiveInstancesMap = new HashMap<>();

        for (Map.Entry<String, Set<String>> entry : validationRuleTypesMap.entrySet()) {
            String validationRuleInstanceId = entry.getKey();
            Set<String> validationObjectTypes = entry.getValue();
            List<MetaClassInstance> metaClassInstances = elementInstanceGivenTypesMap.entrySet().stream().
                    filter(elementGivenTypesEntry -> elementGivenTypesEntry.getValue().stream().
                            anyMatch(validationObjectTypes::contains)).map(Map.Entry::getKey).collect(Collectors.toList());
            validationRuleEffectiveInstancesMap.put(validationRuleInstanceId, metaClassInstances);
        }


        //校验逻辑
        //多线程填充结果时候有线程安全问题，用Vector确保不会少填充结果
        List<ValidatorResultVo> customizationValidationRuleResult = Collections.synchronizedList(new ArrayList<>());

        CompletableFuture<Void> allOf = CompletableFuture.allOf(validationRuleEffectiveInstancesMap.entrySet().stream().map(entry -> {
            String validationRuleInstanceId = entry.getKey();
            List<MetaClassInstance> metaClassInstances = entry.getValue();
            List<MapOperation> mapOperationList = validationRuleExpressionMap.get(validationRuleInstanceId);
            List<List<MetaClassInstance>> partition = Lists.partition(metaClassInstances, PARTITION_SIZE);
            return partition.stream().map(elementList ->
                    //校验逻辑
                    CompletableFuture.supplyAsync(() -> validCustomizationRules(projectId, elementList, mapOperationList,
                                    modelPropertyInfoMap, customizationValidationRuleModelPropertyInfoMap.get(validationRuleInstanceId))).
                            thenApply(customizationValidationRuleResult::addAll)
            ).collect(Collectors.toList());
        }).flatMap(Collection::parallelStream).toArray(CompletableFuture[]::new));
        allOf.join();

        return customizationValidationRuleResult;
    }

    /**
     * 执行脚本计算逻辑
     *
     * @param projectId
     * @param elementList
     * @param mapOperationList
     * @param modelPropertyInfoMap
     * @param customizationValidationRuleModelPropertyInfo
     * @return
     */
    private List<ValidatorResultVo> validCustomizationRules(String projectId,
                                                            List<MetaClassInstance> elementList,
                                                            List<MapOperation> mapOperationList,
                                                            Map<String, ModelPropertyInfo> modelPropertyInfoMap,
                                                            ModelPropertyInfo customizationValidationRuleModelPropertyInfo) {
        Map<String, Map<String, CustomListHolder>> allCustomListHolderMap = new HashMap<>();
        navigationService.queryCustomizeDataByOrderTraversal(projectId, elementList, mapOperationList, allCustomListHolderMap);
        Map<String, CustomListHolder> valueMap = new HashMap<>();
        for (Map<String, CustomListHolder> customListHolderMap : allCustomListHolderMap.values()) {
            for (Map.Entry<String, CustomListHolder> entry : customListHolderMap.entrySet()) {
                valueMap.putIfAbsent(entry.getKey(), new CustomListHolder());
                valueMap.get(entry.getKey()).add(entry.getValue());
            }
        }
        List<ValidatorResultVo> resultVos = new ArrayList<>();
        for (Map.Entry<String, CustomListHolder> instanceValueEntry : valueMap.entrySet()) {
            String instanceId = instanceValueEntry.getKey();
            CustomListHolder customListHolder = instanceValueEntry.getValue();
            if (CollectionUtils.isEmpty(customListHolder.getBooleanList()) ||
                    customListHolder.getBooleanList().stream().noneMatch(e -> Objects.equals(e, Boolean.TRUE))) {
                continue;
            }
            ValidatorAnnoation annotation = new ValidatorAnnoation();
            annotation.setValidationRuleErrorMessage(customizationValidationRuleModelPropertyInfo.queryStringValue(UMLDefinitionConstants.Customization_ValidationRule_ErrorMessage));
            annotation.setValidationRuleInstanceId(customizationValidationRuleModelPropertyInfo.getInstanceId());
            annotation.setValidationRuleSeverity(getSeverityCode(customizationValidationRuleModelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_Severity)));
            MetaClassInstance ruleType = customizationValidationRuleModelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_RuleType);
            annotation.setRuleType(ruleType.getId());
            annotation.setInstanceId(instanceId);

            ModelPropertyInfo modelPropertyInfo = modelPropertyInfoMap.get(instanceId);
            ValidatorResultVo validatorResultVo = new ValidatorResultVo();
            validatorResultVo.setOwnerId(modelPropertyInfo.getInstance().getOwnerId());
            validatorResultVo.setInstanceId(modelPropertyInfo.getInstanceId());
            validatorResultVo.setNamespace(fetchNamespace(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName)));
            validatorResultVo.setAnnoations(Collections.singletonList(annotation));
            resultVos.add(validatorResultVo);

        }
        return resultVos;
    }


    /**
     * 使用内置规则校验模型
     *
     * @param validElementDto
     * @param builtInValidationAbbreviationModelPropertyInfoMap
     * @param elements
     * @return 校验结果
     */
    private List<ValidatorResultVo> checkByBuiltinValidationRules(ValidSpecifiedRangeElementDTO validElementDto,
                                                                  Map<String, ModelPropertyInfo> builtInValidationAbbreviationModelPropertyInfoMap,
                                                                  List<MetaClassInstance> elements) {
        String projectId = validElementDto.getProjectId();
        //多线程填充结果时候有线程安全问题，用Vector确保不会少填充结果
        List<ValidatorResultVo> builtinValidationRuleResult = Collections.synchronizedList(new ArrayList<>());

        List<String> ruleKeys = new ArrayList<>(builtInValidationAbbreviationModelPropertyInfoMap.keySet());

        //查询这些元素的指定的所有属性
        List<ModelPropertyInfo> modelPropertyInfoList = modelPropertyInfoService.createModelPropertyInfoList(projectId, elements, PROPERTY_IDS);

        Map<String, Set<String>> givenTypesMap = internalUmlService.getGivenTypes(projectId,
                modelPropertyInfoList.stream().map(ModelPropertyInfo::getInstance).collect(Collectors.toList()));

        Map<String, Map<String, IValidator>> validatorMap = elementCheckRuleManager.getValidatorMapByRuleKey(ruleKeys);

        //校验逻辑
        List<CompletableFuture<Boolean>> list = modelPropertyInfoList.stream().map(t ->
                CompletableFuture.supplyAsync(() -> {
                    Set<String> notActiveRuleKeys = new HashSet<>();
                    //如果当前模型不属于使用模式下的泳道模型id，那么使用模式的泳道校验规则不生效
                    if (!validElementDto.getUsageModeInstanceIds().contains(t.getInstanceId())) {
                        notActiveRuleKeys.add(ElementCheckRuleKey.USAGE_MODE_ALLOCATE_ACTIVITY_PARTITION_ACTIONS_ON_CLIENT_ENDS_VALIDATOR);
                    }
                    //如果当前模型不属于定义模式下的泳道模型id，那么定义模式的泳道校验规则不生效
                    if (!validElementDto.getDefinitionModeInstanceIds().contains(t.getInstanceId())) {
                        notActiveRuleKeys.add(ElementCheckRuleKey.DEFINITION_MODE_ALLOCATE_ACTIVITY_PARTITION_ACTIONS_ON_CLIENT_ENDS_VALIDATOR);
                    }
                    return validateRules(t, givenTypesMap.get(t.getInstanceId()), validatorMap, notActiveRuleKeys);
                }).thenApply(builtinValidationRuleResult::addAll)).collect(Collectors.toList());

        //如果需要进行共享包校验
        if (ruleKeys.stream().anyMatch(ElementCheckRuleKey.SHARED_ELEMENT_VALIDATOR::equals)) {
            final List<MetaClassInstance> finalElements = elements;
            list.add(CompletableFuture.supplyAsync(() -> validateSharePackageElements(projectId, finalElements)).thenApply(builtinValidationRuleResult::addAll));
        }
        //元素重名校验
        if (CollUtil.contains(ruleKeys, ElementCheckRuleKey.ELEMENT_DUPLICATE_NAME)) {
            list.add(CompletableFuture.supplyAsync(() -> validateElementDuplicateName(modelPropertyInfoList, givenTypesMap)).thenApply(builtinValidationRuleResult::addAll));
        }
        CompletableFuture<Void> allOf = CompletableFuture.allOf(list.toArray(new CompletableFuture[0]));
        allOf.join();

        //对结果进行处理
        builtinValidationRuleResult.forEach(validatorResultVo -> {
            if (CollectionUtils.isNotEmpty(validatorResultVo.getAnnoations())) {
                ValidatorAnnoation annoation = validatorResultVo.getAnnoations().get(0);
                ModelPropertyInfo modelPropertyInfo = builtInValidationAbbreviationModelPropertyInfoMap.get(annoation.getRuleKey());
                if (Objects.nonNull(modelPropertyInfo)) {
                    annoation.setValidationRuleInstanceId(modelPropertyInfo.getInstanceId());
                    Integer severityCode = getSeverityCode(modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_Severity));

                    annoation.setValidationRuleSeverity(severityCode);
                    MetaClassInstance ruleType = modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_RuleType);
                    annoation.setRuleType(ruleType.getId());

                    annoation.setValidationRuleErrorMessage(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.Customization_ValidationRule_ErrorMessage));
                }
            }
        });
        return builtinValidationRuleResult;
    }

    private Integer getSeverityCode(MetaClassInstance severityInstance) {
        String severity = Optional.ofNullable(severityInstance).map(MetaClassInstance::getId).orElse(null);
        return ValidationSeverityEnum.fromEnumCodeToCode(severity);
    }

    private List<ValidatorResultVo> validateElementDuplicateName(List<ModelPropertyInfo> finalModelPropertyInfos, Map<String, Set<String>> givenTypesMap) {
        Map<String, ModelPropertyInfo> checkMap = new HashMap<>();
        Map<String, ModelPropertyInfo> duplicateMap = new HashMap<>();
        for (ModelPropertyInfo propertyInfo : finalModelPropertyInfos) {
            Set<String> givenTypes = givenTypesMap.get(propertyInfo.getInstanceId());
            if (CollUtil.contains(givenTypes, UMLDefinitionConstants.Relationship)
                    || CollUtil.contains(givenTypes, UMLDefinitionConstants.Property)
                    || CollUtil.contains(givenTypes, UMLDefinitionConstants.Slot)
                    || CollUtil.contains(givenTypes, UMLDefinitionConstants.InstanceSpecification)
                    || CollUtil.contains(givenTypes, UMLDefinitionConstants.TypedElement)
            ) {
                continue;
            }
            StrBuilder key = new StrBuilder();
            key.append(propertyInfo.getInstance().getClassifier().getId());
            key.append(propertyInfo.queryProperty(UMLDefinitionConstants.NamedElement_name));
            key.append(propertyInfo.queryProperty(UMLDefinitionConstants.Element_appliedStereotype));
            if (!checkMap.containsKey(key.toString())) {
                checkMap.put(key.toString(), propertyInfo);
            } else {
                ModelPropertyInfo modelPropertyInfo = checkMap.get(key.toString());
                duplicateMap.put(modelPropertyInfo.getInstance().getUUID(), modelPropertyInfo);
                duplicateMap.put(propertyInfo.getInstance().getUUID(), propertyInfo);
            }
        }
        List<ValidatorResultVo> result = new ArrayList<>();
        for (ModelPropertyInfo modelPropertyInfo : duplicateMap.values()) {
            ValidatorAnnoation annotation = new ValidatorAnnoation();
            annotation.setErrorMessage("test");
            annotation.setInstanceId(modelPropertyInfo.getInstanceId());
            annotation.setRuleKey(ElementCheckRuleKey.ELEMENT_DUPLICATE_NAME);
            ValidatorResultVo validatorResultVo = new ValidatorResultVo();
            validatorResultVo.setAnnoations(Collections.singletonList(annotation));
            validatorResultVo.setOwnerId(modelPropertyInfo.getInstance().getOwnerId());
            validatorResultVo.setInstanceId(modelPropertyInfo.getInstanceId());
            validatorResultVo.setNamespace(fetchNamespace(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName)));
            result.add(validatorResultVo);
        }
        return result;
    }

    /**
     * 校验共享包
     *
     * @param projectId
     * @param elements
     * @return
     */
    private List<ValidatorResultVo> validateSharePackageElements(String projectId, List<MetaClassInstance> elements) {
        if (CollectionUtils.isEmpty(elements)) {
            return Collections.emptyList();
        }
        List<ValidatorResultVo> validatorResultVos = projectShareService.queryShareResult(projectId, elements);

        validatorResultVos.stream().map(ValidatorResultVo::getAnnoations).filter(CollectionUtils::isNotEmpty).forEach(e -> e.forEach(t -> t.setRuleKey(ElementCheckRuleKey.SHARED_ELEMENT_VALIDATOR)));
        return validatorResultVos;
    }

    /**
     * 校验规则
     *
     * @param modelPropertyInfo 模型信息
     * @param givenTypes        模型类型
     * @param validatorMap      规则
     * @param notActiveRuleKey  本次校验不生效的规则
     * @return
     */
    private List<ValidatorResultVo> validateRules(ModelPropertyInfo modelPropertyInfo,
                                                  Set<String> givenTypes,
                                                  Map<String, Map<String, IValidator>> validatorMap,
                                                  Set<String> notActiveRuleKey) {
        List<ValidatorResultVo> validatorResultVos = new ArrayList<>();
        validatorMap.entrySet().stream().filter(outerEntry -> !notActiveRuleKey.contains(outerEntry.getKey())).forEach(outerEntry -> {
            String ruleKey = outerEntry.getKey();
            List<ValidatorResultVo> tempResult = outerEntry.getValue().entrySet().stream().filter(entry ->
                    givenTypes.contains(entry.getKey()) &&
                            StringUtils.isNotEmpty(entry.getValue().errorMessage()) &&
                            !entry.getValue().validate(modelPropertyInfo.getProjectId(), modelPropertyInfo)).map(entry -> {
                ValidatorAnnoation annotation = new ValidatorAnnoation();
                annotation.setErrorMessage(entry.getValue().errorMessage());
                annotation.setInstanceId(modelPropertyInfo.getInstanceId());
                annotation.setRuleKey(ruleKey);

                ValidatorResultVo validatorResultVo = new ValidatorResultVo();
                validatorResultVo.setAnnoations(Collections.singletonList(annotation));
                validatorResultVo.setOwnerId(modelPropertyInfo.getInstance().getOwnerId());
                validatorResultVo.setInstanceId(modelPropertyInfo.getInstanceId());
                validatorResultVo.setNamespace(fetchNamespace(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName)));
                return validatorResultVo;
            }).collect(Collectors.toList());
            validatorResultVos.addAll(tempResult);
        });
        return validatorResultVos;
    }

    @NotNull
    public List<ValidatorResultVo> checkElements(final ValidElementDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto: ", dto);
        final String projectId = dto.getProjectId();
        final List<String> instanceIds = dto.getInstanceIds();

        List<MetaClassInstance> elements = internalUmlService.fetchInstanceByIds(instanceIds, projectId);
        List<ModelPropertyInfo> models = modelPropertyInfoService.createModelPropertyInfoList(projectId, elements,
                Stream.of(UMLDefinitionConstants.Element_appliedStereotype,
                        UMLDefinitionConstants.NamedElement_qualifiedName).collect(Collectors.toList()));
        return createValidatorResultVo(projectId, models);

    }

    @NotNull
    private List<ValidatorResultVo> createValidatorResultVo(@NotNull final String projectId,
                                                            @NotNull final List<ModelPropertyInfo> models) {
        LogUtil.printOnlineLogs("createValidatorResultVo -> projectId: ", projectId);
        if (CollectionUtils.isEmpty(models)) {
            return new ArrayList<>();
        }
        final Map<String, List<ValidatorAnnoation>> annoations = queryAnnoations(projectId, models);
        return models.stream().filter(it -> annoations.containsKey(it.getInstanceId())).map(model -> {
            ValidatorResultVo result = new ValidatorResultVo();
            result.setInstanceId(model.getInstanceId());
            result.setNamespace(fetchNamespace(model.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName)));
            result.setAnnoations(annoations.get(model.getInstanceId()));
            return result;
        }).collect(Collectors.toList());
    }

    @NotNull
    private Map<String, List<ValidatorAnnoation>> queryAnnoations(String projectId, @NotNull List<ModelPropertyInfo> models) {
        LogUtil.printOnlineLogs("queryAnnoations - >projectId: ", projectId);
        Map<String, List<IValidator>> validatorMap = validatorManage.queryElementValidators(projectId, "element",
                models);
        if (MapUtils.isEmpty(validatorMap)) {
            return Collections.emptyMap();
        }

        Map<String, List<ValidatorAnnoation>> result = new ConcurrentHashMap<>();
        models.forEach(model -> {
            List<IValidator> validators = validatorMap.get(model.getInstanceId());
            if (CollectionUtils.isNotEmpty(validators)) {
                List<ValidatorAnnoation> annoations =
                        validators.stream().filter(validator -> StringUtils.isNotEmpty(validator.errorMessage()) && !validator.validate(projectId, model))
                                .map(validator -> {
                                    ValidatorAnnoation annoation = new ValidatorAnnoation();
                                    annoation.setErrorMessage(validator.errorMessage());
                                    annoation.setInstanceId(model.getInstanceId());
                                    annoation.setSeverity(validator.getSeverity());
                                    return annoation;
                                }).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(annoations)) {
                    result.put(model.getInstanceId(), annoations);
                }
            }
        });

        return result;
    }

    @Nullable
    public String fetchNamespace(String qualifiedName) {
        LogUtil.printOnlineLogs("qualifiedName: ", qualifiedName);
        if (StringUtils.isNotEmpty(qualifiedName)) {
            int index = qualifiedName.lastIndexOf("::");
            if (index > 0) {
                return "模型::" + qualifiedName.substring(0, index);
            } else {
                return "模型";
            }
        }
        return null;
    }

    public List<ValidationModelInstanceVo> queryValidationGroups(String projectId) {
        LogUtil.printOnlineLogs("queryValidationGroups -> projectId:{} ", projectId);

        List<MetaClassInstance> groupInstances = internalUmlService.querySpecifiedInstanceList(projectId, VALIDATION_GROUP_STEREOTYPES);
        return getValidationModelInstanceVos(projectId, groupInstances, VALIDATION_GROUP_STEREOTYPES);

    }

    /**
     * 转换成ValidationModelInstanceVo
     *
     * @param projectId
     * @param instances
     * @return
     */
    private List<ValidationModelInstanceVo> getValidationModelInstanceVos(String projectId, List<MetaClassInstance> instances, Set<String> types) {
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, instances, VALIDATION_QUERY_PROPERTIES);
        Map<String, String> instanceIconMap = modelPropertyInfoService.queryIconBatch(projectId, instances);

        List<ValidationModelInstanceVo> vos = new ArrayList<>();
        for (MetaClassInstance instance : instances) {
            ModelPropertyInfo modelPropertyInfo = modelPropertyInfoMap.get(instance.getId());
            if (types.stream().noneMatch(modelPropertyInfo::checkInstanceType)) {
                continue;
            }
            ValidationModelInstanceVo vo = new ValidationModelInstanceVo();
            vo.setInstanceId(instance.getId());
            vo.setInstance(instance);
            vo.setOwnerId(instance.getOwnerId());
            vo.setInstanceName(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name));
            vo.setQualifiedName(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName));
            List<String> stereotypes = modelPropertyInfo.queryListInstanceValue(UMLDefinitionConstants.Element_appliedStereotype).stream().map(MetaClassInstance::getId).collect(Collectors.toList());
            vo.setMetaClass(instance.getMetaClass().getId());
            vo.setAppliedStereotypes(stereotypes);
            if (iJudgeService.isCreatedInteractive(instance)) {
                vo.setIsInteractive(Boolean.TRUE);
            }
            vo.setIcon(instanceIconMap.get(instance.getId()));
            vos.add(vo);
        }
        return vos;
    }


    public List<ValidationModelInstanceVo> queryValidationModelsOfValidationGroup(String projectId, String validationGroupInstanceId) {
        LogUtil.printOnlineLogs("queryValidationGroups -> projectId:{}, validationGroupInstanceId:{}", projectId, validationGroupInstanceId);
        MetaClassInstance groupInstance = internalUmlService.fetchInstance(validationGroupInstanceId, projectId);
        if (groupInstance == null) {
            return Collections.emptyList();
        }

        List<MetaClassInstance> children = internalUmlService.getChildren(groupInstance, false, projectId);
        List<ValidationModelInstanceVo> validationModelInstanceVos = getValidationModelInstanceVos(projectId, children, VALIDATION_STEREOTYPES);
        validationModelInstanceVos.addAll(queryValidationGroupImportValidationRuleVos(projectId, groupInstance));
        getTreeOfValidationGroup(projectId, validationModelInstanceVos);
        return validationModelInstanceVos;

    }

    private void getTreeOfValidationGroup(String projectId, List<ValidationModelInstanceVo> validationModelInstanceVos) {
        Set<ValidationModelInstanceVo> nextLevelGroups = validationModelInstanceVos.stream().
                filter(e -> e.getAppliedStereotypes().stream().anyMatch(VALIDATION_GROUP_STEREOTYPES::contains)).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(nextLevelGroups)) {
            return;
        }
        List<ValidationModelInstanceVo> notElementImportGroups = nextLevelGroups.stream().filter(e -> Objects.equals(e.getIsElementImport(), Boolean.FALSE)).collect(Collectors.toList());
        for (ValidationModelInstanceVo notElementImportGroup : notElementImportGroups) {
            //查询校验分组导入的校验规则
            List<ValidationModelInstanceVo> elementImportVos = queryValidationGroupImportValidationRuleVos(projectId, notElementImportGroup.getInstance());
            notElementImportGroup.getChildren().addAll(elementImportVos);
        }
        for (ValidationModelInstanceVo validationModelInstanceVo : validationModelInstanceVos) {
            if (Objects.equals(validationModelInstanceVo.getIsElementImport(), Boolean.TRUE)) {
                continue;
            }
            List<MetaClassInstance> childrenInstances = internalUmlService.getChildren(validationModelInstanceVo.getInstance(), false, projectId);
            List<ValidationModelInstanceVo> childrenModelInstanceVos = getValidationModelInstanceVos(projectId, childrenInstances, VALIDATION_STEREOTYPES);
            validationModelInstanceVo.getChildren().addAll(childrenModelInstanceVos);
            getTreeOfValidationGroup(projectId, childrenModelInstanceVos);
        }

    }

    private List<ValidationModelInstanceVo> queryValidationGroupImportValidationRuleVos(String projectId, MetaClassInstance nextLevelGroup) {
        Map<MetaClassInstance, List<MetaClassInstance>> targetElementImportRelationShipMap = queryTargetElementImportRelationShipMap(projectId, nextLevelGroup);
        List<ValidationModelInstanceVo> elementImportVos = new ArrayList<>();
        if (MapUtils.isNotEmpty(targetElementImportRelationShipMap)) {
            List<MetaClassInstance> elementImportValidationRules = new ArrayList<>(targetElementImportRelationShipMap.keySet());
            List<String> ownerIds = elementImportValidationRules.stream().map(MetaClassInstance::getOwnerId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            List<MetaClassInstance> ownerMetaClassInstances = internalUmlService.fetchInstanceByIds(ownerIds, projectId);
            Map<String, ValidationModelInstanceVo> groupVoMap = getValidationModelInstanceVos(projectId, ownerMetaClassInstances, VALIDATION_STEREOTYPES).stream().
                    collect(Collectors.toMap(ValidationModelInstanceVo::getInstanceId, Function.identity(), (k1, k2) -> k1));

            Map<String, List<ValidationModelInstanceVo>> ownerIdValidationRuleMap = getValidationModelInstanceVos(projectId, elementImportValidationRules, VALIDATION_STEREOTYPES).
                    stream().collect(Collectors.groupingBy(ValidationModelInstanceVo::getOwnerId));
            groupVoMap.forEach((ownerId, vo) -> {
                List<ValidationModelInstanceVo> ownerChildren = ownerIdValidationRuleMap.getOrDefault(ownerId, Collections.emptyList());
                ownerChildren.forEach(e -> {
                    e.setIsElementImport(Boolean.TRUE);
                    e.setElementImportRelationShipIds(targetElementImportRelationShipMap.get(e.getInstance()).stream().map(MetaClassInstance::getId).collect(Collectors.toList()));
                });
                vo.setChildren(ownerChildren);
                vo.setIsElementImport(Boolean.TRUE);
            });
            elementImportVos.addAll(groupVoMap.values());
        }
        return elementImportVos;
    }

    public ValidationModelInstanceVo queryValidationModelTree(String projectId) {
        LogUtil.printOnlineLogs("queryValidationModelTree -> projectId:{}", projectId);
        final Project project = projectManager.getProject(projectId);
        if (Objects.isNull(project)) {
            throw AbortExecutionException.build(ErrorCode.PROJECT_NOT_FOUND);
        }
        ValidationModelInstanceVo rootModelVo = getRootModelVo(projectId, project);


        Map<String, MetaClassInstance> instanceMap = new HashMap<>();
        List<MetaClassInstance> metaClassInstances = internalUmlService.querySpecifiedInstanceList(projectId, VALIDATION_STEREOTYPES);
        while (CollectionUtils.isNotEmpty(metaClassInstances)) {
            metaClassInstances.forEach(instance -> instanceMap.put(instance.getId(), instance));
            List<String> parentLevelInstanceIds = metaClassInstances.stream().map(MetaClassInstance::getOwnerId).filter(Objects::nonNull).collect(Collectors.toList());
            metaClassInstances = internalUmlService.fetchInstanceByIds(parentLevelInstanceIds, projectId);
        }
        List<MetaClassInstance> allMetaClassInstances = new ArrayList<>(instanceMap.values());
        List<ValidationModelInstanceVo> validationModelInstanceVos = getValidationModelInstanceVos(projectId, allMetaClassInstances, STEREOTYPES);
        Map<String, List<ValidationModelInstanceVo>> ownerIdInstanceMap = validationModelInstanceVos.stream().filter(e -> Objects.nonNull(e.getOwnerId())).collect(Collectors.groupingBy(ValidationModelInstanceVo::getOwnerId));

        List<ValidationModelInstanceVo> curVos = Collections.singletonList(rootModelVo);

        while (CollectionUtils.isNotEmpty(curVos)) {
            List<ValidationModelInstanceVo> allNextLevelVos = new ArrayList<>();
            for (ValidationModelInstanceVo curVo : curVos) {
                List<ValidationModelInstanceVo> nextLevelVos = ownerIdInstanceMap.getOrDefault(curVo.getInstanceId(), Collections.emptyList());
                curVo.setChildren(nextLevelVos);
                allNextLevelVos.addAll(nextLevelVos);
            }
            curVos = allNextLevelVos;

        }
        return rootModelVo;
    }

    private ValidationModelInstanceVo getRootModelVo(String projectId, Project project) {
        String rootModel = project.getRootModel();
        MetaClassInstance rootInstance = internalUmlService.fetchInstance(rootModel, projectId);

        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, Collections.singletonList(rootInstance), VALIDATION_QUERY_PROPERTIES);
        ValidationModelInstanceVo rootVo = new ValidationModelInstanceVo();
        rootVo.setInstance(rootInstance);
        Map<String, String> iconMap = modelPropertyInfoService.queryIconBatch(projectId, Collections.singletonList(rootInstance));
        rootVo.setIcon(iconMap.get(rootInstance.getId()));
        rootVo.setInstanceId(rootInstance.getId());
        rootVo.setMetaClass(rootInstance.getMetaClass().getId());
        rootVo.setMetaClass(rootInstance.getMetaClass().getId());
        rootVo.setInstanceName(modelPropertyInfoMap.get(rootInstance.getId()).queryStringValue(UMLDefinitionConstants.NamedElement_name));
        rootVo.setQualifiedName(modelPropertyInfoMap.get(rootInstance.getId()).queryStringValue(UMLDefinitionConstants.NamedElement_qualifiedName));
        rootVo.setIsInteractive(true);
        rootVo.setOwnerId(null);
        return rootVo;
    }

    public List<String> queryValidationRuleInstanceIds(ValidationModelQueryDTO queryDTO) {
        List<String> validationGroupInstanceIds = queryDTO.getValidationGroupInstanceIds();
        String projectId = queryDTO.getProjectId();
        Set<String> validationModelTypes = queryDTO.getValidationModelTypes();
        if (CollectionUtils.isEmpty(validationModelTypes)) {
            validationModelTypes = VALIDATION_GROUP_STEREOTYPES;
        }

        List<MetaClassInstance> groupInstances;
        if (CollectionUtils.isEmpty(validationGroupInstanceIds)) {
            groupInstances = internalUmlService.querySpecifiedInstanceList(projectId, validationModelTypes);
        } else {
            groupInstances = internalUmlService.fetchInstanceByIds(validationGroupInstanceIds, projectId);
        }

        List<String> validationInstanceIds = internalUmlService.getChildrenCascadeIds(projectId, groupInstances.stream().map(MetaClassInstance::getId).collect(Collectors.toList()), true);
        List<MetaClassInstance> validationMetaClassInstances = internalUmlService.fetchInstanceByIds(validationInstanceIds, projectId);
        List<MetaClassInstance> validationRuleInstances = validationMetaClassInstances.stream().
                filter(e -> internalUmlService.checkInstanceType(projectId, e, UMLDefinitionConstants.Customization_ValidationRule)).collect(Collectors.toList());

        List<MetaClassInstance> validationGroupInstances = validationMetaClassInstances.stream().filter(e -> !internalUmlService.checkInstanceType(projectId, e,
                UMLDefinitionConstants.Customization_ValidationRule)).collect(Collectors.toList());

        //查询元素导入引入的校验规则
        List<MetaClassInstance> validationGroupElementImportValidationRules = queryValidationGroupElementImportValidationRules(projectId, validationGroupInstances);
        validationRuleInstances.addAll(validationGroupElementImportValidationRules);

        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId, validationRuleInstances,
                Collections.singletonList(UMLDefinitionConstants.Customization_ValidationRule_Severity));
        Set<String> severityKinds = ValidationSeverityEnum.getSeverityKinds(queryDTO.getSeverity());
        //如果需要过滤出内置的校验分组，这里进行二次过滤
        if (Objects.equals(queryDTO.getIsFilterBuiltinRule(), Boolean.TRUE)) {
            validationRuleInstances = validationRuleInstances.stream().filter(e -> !iJudgeService.isCreatedInteractive(e)).collect(Collectors.toList());
        }
        return validationRuleInstances.stream().filter(instance -> {
            ModelPropertyInfo modelPropertyInfo = modelPropertyInfoMap.get(instance.getId());
            MetaClassInstance severityInstance = modelPropertyInfo.queryInstanceValue(UMLDefinitionConstants.Customization_ValidationRule_Severity);
            return modelPropertyInfo.checkInstanceType(UMLDefinitionConstants.Customization_ValidationRule) && Objects.nonNull(severityInstance)
                    && severityKinds.contains(severityInstance.getId());
        }).map(MetaClassInstance::getId).distinct().collect(Collectors.toList());

    }

    private List<MetaClassInstance> queryValidationGroupElementImportValidationRules(String projectId, List<MetaClassInstance> groupInstances) {
        Map<String, List<MetaClassInstance>> elementMentRelationShipsMap = internalUmlService.queryResolveRelationShips(projectId, groupInstances,
                Collections.singletonList(UMLDefinitionConstants.ElementImport));
        List<MetaClassInstance> relationShipInstances = elementMentRelationShipsMap.values().stream().flatMap(Collection::parallelStream).collect(Collectors.toList());
        List<MetaClassInstance> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(relationShipInstances)) {
            Map<MetaClassInstance, List<MetaClassInstance>> relationTargetsMap = internalUmlService.queryRelationTargets(projectId, relationShipInstances);
            List<MetaClassInstance> relationTargetInstances = relationTargetsMap.values().stream().flatMap(Collection::parallelStream).collect(Collectors.toList());
            result.addAll(relationTargetInstances);
        }
        return result;
    }

    /**
     * 查询目标模型与引入关系的map
     *
     * @param projectId
     * @param groupInstance
     * @return Map<MetaClassInstance, List < MetaClassInstance>> key: 目标模型，value:引入关系集合
     */
    private Map<MetaClassInstance, List<MetaClassInstance>> queryTargetElementImportRelationShipMap(String projectId, MetaClassInstance groupInstance) {
        List<MetaClassInstance> relationShipInstances = relationService.queryResolveRelations(projectId, groupInstance,
                Collections.singletonList(UMLDefinitionConstants.ElementImport), false);

        Map<MetaClassInstance, List<MetaClassInstance>> relationShipMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(relationShipInstances)) {
            Map<MetaClassInstance, List<MetaClassInstance>> relationTargetsMap = internalUmlService.queryRelationTargets(projectId, relationShipInstances);
            relationTargetsMap.forEach((relationShip, targetInstances) -> {
                for (MetaClassInstance targetInstance : targetInstances) {
                    List<MetaClassInstance> relationShipInstancesOfTargets = relationShipMap.getOrDefault(targetInstance, new ArrayList<>());
                    relationShipInstancesOfTargets.add(relationShip);
                    relationShipMap.put(targetInstance, relationShipInstancesOfTargets);

                }
            });
        }
        return relationShipMap;
    }
}
